public class Solution {
    public static void main(String[] args) {
        Solution test = new Solution();
        int[] testArr = new int[]{1, 0};
        test.duplicateZeros(testArr);
        for (int x :
                testArr) {
            System.out.print(x + " ");
        }
    }

    public void moveZeroes(int[] nums) {
        /**
         * 双指针-移动零*/
        int partition = -1;
        for(int cur = 0; cur < nums.length; cur ++) {
            // 因为partition表示最后一个非零元素的下标
            // 因此当cur遇见新的非零元素时，需要更新partition的值
            // 简单来说就是partition++后，与非零元素进行交换
            if(nums[cur] != 0) {
                partition ++;
                swap(nums, partition, cur);
            }
        }
    }

    private static void swap(int[] array, int left, int right) {
        /**
         * 交换函数*/
        int temp = array[left];
        array[left] = array[right];
        array[right] = temp;
    }

    public void duplicateZeros(int[] arr) {
        /**
         * 复写零*/
        // 1 通过双指针的方式找到最后一个元素所在位置
        int n = arr.length;
        int fast = -1;
        int slow = -1;
        while(fast < n-1) {
            // 注意：此处的顺序应当为，两者同进1，后再判断slow的值，若为0，fast再进1
            fast ++;
            slow ++;
            if(arr[slow] == 0) {
                fast ++;
            }
        }
        // 2 复写（需要判断最后一个元素是否落单）
        // -记录开始复写的位置
        int start = n-1;
        if(fast == n) {
            // -fast==n，说明最后一个复写的元素是0，且这个0只实际复写一个，而不是两个
            // -也就是：slow已经指向0了，但实际他只复写1个，这属于特殊情况，需要额外判断
            arr[n-1] = 0;
            start = n-2;
            slow --;
        }
        while(slow >= 0) {
            if(arr[slow] == 0) {
                arr[start] = 0;
                start --;
            }
            arr[start] = arr[slow];
            start --;
            slow --;
        }
    }
}
